#include <Scanner/token.h>

const char* Token::TypeSymbol(TokenType type)
{
    switch (type)
    {
    case TokenType::PLUS: // +
        return "+";
    case TokenType::MINUS: // -
        return "-";
    case TokenType::MUL: // *
        return "*";
    case TokenType::DIV: // /
        return "/";
    case TokenType::LPAREN: // (
        return "(";
    case TokenType::RPAREN: // )
        return ")";
    case TokenType::LBRACE: // {
        return "{";
    case TokenType::RBRACE: // }
        return "}";
    case TokenType::COMMA: // ,
        return ",";
    case TokenType::DOT: // .
        return ".";
    case TokenType::COLON: //:
        return ":";
    case TokenType::SEMICOLON: // ;
        return ";";
    case TokenType::PLUS_PLUS:
        return "++";
    case TokenType::MINUS_MINUS:
        return "--";
    case TokenType::QUESTION_MARK:  // ?
        return "?";

        // bool
    case TokenType::BANG: // !
        return "!";
    case TokenType::BANGEQ: // !=
        return "!=";
    case TokenType::EQ: // =
        return "=";
    case TokenType::EQEQ: // ==
        return "==";
    case TokenType::GT: // >
        return ">";
    case TokenType::GTE: // >=
        return ">=";
    case TokenType::LT: // LT
        return "<";
    case TokenType::LTE: // <=
        return "<=";

        // primary
    case TokenType::NUMBER: // number
        return "NUMBER";
    case TokenType::STRING: // string
        return "STRING";
    case TokenType::IDENTIFIER: // identifier
        return "IDENTIFIER";

        // keyword
    case TokenType::NIL: // nil, represent undefined variable
        return "nil";
    case TokenType::TRUE: // true
        return "true";
    case TokenType::FALSE: // false
        return "false";
    case TokenType::VAR:
        return "var";
    case TokenType::CLASS:
        return "class";
    case TokenType::THIS:
        return "this";
    case TokenType::SUPER:
        return "super";
    case TokenType::IF:
        return "if";
    case TokenType::ELSE:
        return "else";
    case TokenType::FOR:
        return "for";
    case TokenType::WHILE:
        return "while";
    case TokenType::BREAK:
        return "break";
    case TokenType::CONTINUE:
        return "continue";
    case TokenType::FUNC:
        return "func";
    case TokenType::RETURN:
        return "return";
    case TokenType::AND:
        return "and";
    case TokenType::OR:
        return "or";

    case TokenType::PRINT:
        return "print";

    case TokenType::END_OF_FILE:
        return "EOF";
    case TokenType::ERROR:
        return "ERROR";
    }

    return "unreachable";
}

const char* Token::TypeName()
{
    switch (this->type)
    {
    case TokenType::PLUS: // +
        return "PLUS";
    case TokenType::MINUS: // -
        return "MINUS";
    case TokenType::MUL: // *
        return "MUL";
    case TokenType::DIV: // /
        return "DIV";
    case TokenType::LPAREN: // (
        return "LPAREN";
    case TokenType::RPAREN: // )
        return "RPAREN";
    case TokenType::LBRACE: // [
        return "LBRACE";
    case TokenType::RBRACE: // ]
        return "RBRACE";
    case TokenType::COMMA: // ,
        return "COMMA";
    case TokenType::DOT: // .
        return "DOT";
    case TokenType::COLON: //:
        return "PLUS";
    case TokenType::SEMICOLON: // ;
        return "SEMICOLON";
    case TokenType::PLUS_PLUS:
        return "PLUS_PLUS";
    case TokenType::MINUS_MINUS:
        return "MINUS_MINUS";
    case TokenType::QUESTION_MARK:  // ?
        return "QUESTION_MARK";

        // bool
    case TokenType::BANG: // !
        return "BANG";
    case TokenType::BANGEQ: // !=
        return "BANGEQ";
    case TokenType::EQ: // =
        return "EQ";
    case TokenType::EQEQ: // ==
        return "EQEQ";
    case TokenType::GT: // >
        return "GT";
    case TokenType::GTE: // >=
        return "GTE";
    case TokenType::LT: // LT
        return "LT";
    case TokenType::LTE: // <=
        return "LTE";

        // primary
    case TokenType::NUMBER: // number
        return "NUMBER";
    case TokenType::STRING: // string
        return "STRING";
    case TokenType::IDENTIFIER: // identifier
        return "IDENTIFIER";

        // keyword
    case TokenType::NIL: // nil, represent undefined variable
        return "NIL";
    case TokenType::TRUE: // true
        return "TRUE";
    case TokenType::FALSE: // false
        return "FALSE";
    case TokenType::VAR:
        return "VAR";
    case TokenType::CLASS:
        return "CLASS";
    case TokenType::THIS:
        return "THIS";
    case TokenType::SUPER:
        return "IDENTIFIER";
    case TokenType::IF:
        return "IF";
    case TokenType::ELSE:
        return "ELSE";
    case TokenType::FOR:
        return "FOR";
    case TokenType::WHILE:
        return "WHILE";
    case TokenType::BREAK:
        return "BREAK";
    case TokenType::CONTINUE:
        return "CONTINUE";
    case TokenType::FUNC:
        return "FUNC";
    case TokenType::RETURN:
        return "RETURN";
    case TokenType::AND:
        return "AND";
    case TokenType::OR:
        return "OR";

    case TokenType::PRINT:
        return "PRINT";

    case TokenType::END_OF_FILE:
        return "EOF";
    case TokenType::ERROR:
        return "ERROR";
    }

    return "unreachable";
}
